import javax.microedition.lcdui.*;
import java.io.InputStream;

#define Read32() (int)(data[offset++]&0xFF) | ((data[offset++]&0xFF)<<8) | ((data[offset++]&0xFF)<<16) | ((data[offset++]&0xFF)<<24)

#define Read16() (short)(data[offset++]&0xFF) + ((data[offset++]&0xFF)<<8)

#define Read8() (byte)(data[offset++]&0xFF)

#define ReadARGB() ((data[offset++]&0xFF)<<16) | ((data[offset++]&0xFF)<<8) | (data[offset++]&0xFF) | ((data[offset++]&0xFF)<<24)

#include "defines.h"
/* ---------------------------------

Sprite constant:
	TRANS_NONE				0
	TRANS_ROT90				5	// quay cung chieu kim dh
	TRANS_ROT180			3
	TRANS_ROT270			6
	TRANS_MIRROR 			2	//doi xung qua truc tung, chieu doc
	TRANS_MIRROR_ROT90 		7
	TRANS_MIRROR_ROT180		1
	TRANS_MIRROR_ROT270		4

------------------------------------ */
public class ASprite
{
	public final int NONE					= 0;
	public final int ROT90					= 5;
	public final int ROT180					= 3;
	public final int ROT270					= 6;
	public final int MIRROR					= 2;
	public final int MIRROR_ROT90			= 7;
	public final int MIRROR_ROT180			= 1;
	public final int MIRROR_ROT270			= 4;
	// drawRegion(Image src, int x_src, int y_src, int width, int height, int transform, int x_dest, int y_dest, int anchor)
	// Format of Sprite file
	//	4 bytes: check sprite file (0xFF00FF00)
	//	1 byte:  data format type
	//	4 bytes: file size
	//	4 bytes: number of modules
	//	16 bytes: X, Y, W, H
	//	data for each sprite, 4byte/pixel
	
	final int SPRIRE_MASK = 0xFF00FF00;
	private byte m_bFormatType;
	private int m_iFileSize;
	private int m_iModulesNo;
	
	private int offset = 0;
	
	private int[] m_aModulesX = null;
	private int[] m_aModulesY = null;
	private int[] m_aModulesW = null;
	private int[] m_aModulesH = null;
	private byte[] data;
	private Image[] m_imgModules = null;
	
	private static Image s_imgBuffer = null;
	private static int[] s_rgbData = null;
	private static int s_iAlphaColor = 0;
	
	ASprite(){};
	
	boolean LoadSprite(String name)
	{
		offset = 0;
		try
		{
			System.gc();
			InputStream is = this.getClass().getResourceAsStream(name);
			m_iFileSize = is.available();
			
#ifdef USE_DEBUG_SPRITE_LOADING
			System.out.println("File Size: "+m_iFileSize);
#endif
			
			data = new byte[m_iFileSize];
			is.read(data);
			
			// read sprite mask check
			int mask = Read32();
			System.out.println(">>>>>>>>>>>>>>>>"+0xAAFF00BB);
			if(SPRIRE_MASK != mask)
			{
				System.out.println("Not sprite format file!");
				return false;
			}
			
			// read for type of sprite
			m_bFormatType = Read8();
#ifdef USE_DEBUG_SPRITE_LOADING
			System.out.println("Format type: "+m_bFormatType);
#endif
			
			// move over 4 bytes to read fizesize
			offset+=4;
			
			// Load Modules
			LoadModules();
			
		}
		catch(Exception e)
		{
			System.out.println("LoadSprite error info: " + e.getMessage());
			return false;
		}
		data = null;
		System.gc();
		return true;
	}
	
	private int LoadModules()
	{
		// read number of modules (4 bytes)
		m_iModulesNo = Read32();
#ifdef USE_DEBUG_SPRITE_LOADING
		System.out.println("Number of Modules: "+m_iModulesNo);
#endif
		
		// int moduleSize = 0;
		int length = 0;
		
		if(m_iModulesNo > 0)
		{			
			m_aModulesX = new int[m_iModulesNo];
			m_aModulesY = new int[m_iModulesNo];
			m_aModulesW = new int[m_iModulesNo];
			m_aModulesH = new int[m_iModulesNo];
			m_imgModules = new Image[m_iModulesNo];
			
			for(int i=0; i<m_iModulesNo; i++)
			{
				m_aModulesX[i] = Read32();
				m_aModulesY[i] = Read32();
				m_aModulesW[i] = Read32();
				m_aModulesH[i] = Read32();
				
				length = m_aModulesW[i]*m_aModulesH[i];
				int[] img_data = new int[length];
				
				for(int k=0; k<length; k++)
				{
					img_data[k] = ReadARGB();
				}
				
				m_imgModules[i] = Image.createRGBImage(img_data, m_aModulesW[i], m_aModulesH[i], true);
				img_data = null;
			}
		}
		return offset;
	}
	
	int NumOfModules()
	{
		return m_iModulesNo;
	}
	
	byte FormatType()
	{
		return m_bFormatType;
	}
	
	int GetModuleWidth(int id)
	{
		return m_aModulesW[id];
	}
	
	int GetModuleHeight(int id)
	{
		return m_aModulesH[id];
	}
	
	void PaintModule(Graphics g, int id, int x, int y)
	{
		if(m_imgModules[id] != null)
			g.drawImage(m_imgModules[id], x, y, 0);
		else
			System.out.println("NULL");
	}
	
	void PaintModule(Graphics g, int id, int x, int y, int flags)
	{
		if(flags == NONE)
		{
			PaintModule(g, id, x, y);
		}
		else
		{
			if(m_imgModules[id] != null)
				g.drawRegion(m_imgModules[id], 0, 0, m_aModulesW[id], m_aModulesH[id], flags, x, y, 0);
			else
				System.out.println("NULL");
		}
	}
	
	void PrintInfo()
	{
		System.out.println("Sprite format type: "+m_bFormatType);
		System.out.println("Sprite size:        "+m_iFileSize);
		System.out.println("Number of Modules:  "+m_iModulesNo);
		for(int i=0; i<m_iModulesNo; i++)
		{
			System.out.println("	Module "+i+":");
			System.out.println("		X=" + m_aModulesX[i]+" Y= " + m_aModulesY[i] + " W= " + m_aModulesW[i] + " H= " + m_aModulesH[i]);
		}
	}
	
	static void SetAlphaColor(int ARGB)
	{
		s_iAlphaColor = ARGB;
	}
	static void SetAlphaColor(int alpha, int red, int green, int blue)
	{
		s_iAlphaColor = (alpha<<24)|(red<<16)|(green<<8)|blue;
	}
	static int GetAlphaColor()
	{
		return s_iAlphaColor;
	}
	static void FillAlphaRect(Graphics g, int x, int y, int w, int h)
	{
		System.out.println("alpha color: "+(s_iAlphaColor>>24));
		if(w*h==0 || (s_iAlphaColor>>24)<20)
			return;
		System.out.println("<<<<<<<<<<<<<<<<<<<<<<<");
		s_rgbData = new int[w*h];
		for(int i=0; i<w*h; i++)
		{
			s_rgbData[i] = s_iAlphaColor;
		}
		s_imgBuffer = Image.createRGBImage(s_rgbData, w, h, (s_iAlphaColor>>24)!=255);
		g.drawImage(s_imgBuffer, x, y, 0);
		s_rgbData = null;
	}
	
	void Free()
	{
		data = null;
		m_aModulesX = null;
		m_aModulesY = null;
		m_aModulesW = null;
		m_aModulesH = null;
		m_imgModules = null;
		
		System.gc();
	}
}